#include "ASButton.h"

#define AS_TEXT_BUTTON_DISABLE_COLOR 0x999999

static ASVOID as_ctrl_text_button_paint(as_control* ctrl_p)
{
    as_button* button_p = (as_button*)ctrl_p;
    as_rect* area_p = NULL;
    ASINT layer;

    if(!button_p || !button_p->elem.label || button_p->status < AS_BUTTON_UP || button_p->status >= AS_BUTTON_TYPE_MAX)
        return;

    area_p = &ctrl_p->area;
    layer = ctrl_p->show_hdlr;

    if(layer < 0 || as_set_layer_clip_ex(layer, area_p) == AS_IGNORE)
        return;

    if(button_p->status == AS_BUTTON_UP)
    {
        button_p->elem.label->base.paint_hdlr((as_control*)button_p->elem.label);
    }
    else if(button_p->status == AS_BUTTON_DISABLE)
    {
        ASUINT color;
        button_p->elem.label->get_text_color((as_control*)button_p->elem.label, &color);
        button_p->elem.label->set_text_color((as_control*)button_p->elem.label, AS_TEXT_BUTTON_DISABLE_COLOR);
        button_p->elem.label->base.paint_hdlr((as_control*)button_p->elem.label);
        button_p->elem.label->set_text_color((as_control*)button_p->elem.label, color);
    }
    else //if(button_p->status == AS_BUTTON_DOWN)
    {
        ASINT text_y_off = button_p->elem.label->text_y_off;
        ASINT text_x_off = button_p->elem.label->text_x_off;
        button_p->elem.label->text_y_off++;
        button_p->elem.label->base.paint_hdlr((as_control*)button_p->elem.label);
        button_p->elem.label->set_text_offset((as_control*)button_p->elem.label, text_x_off, text_y_off);
    }

    as_reset_layer_clip(layer);
}

static ASVOID as_ctrl_image_button_paint(as_control* ctrl_p)
{
    as_button* button_p = (as_button*)ctrl_p;
    as_rect* area_p = NULL;
    ASINT layer;

    if(!ctrl_p)
        return;

    area_p = &ctrl_p->area;
    layer = ctrl_p->show_hdlr;

    if(layer < 0 || as_set_layer_clip_ex(layer, area_p) == AS_IGNORE)
        return;

    if(button_p->status >= AS_BUTTON_UP && button_p->status < AS_BUTTON_TYPE_MAX)
    {
        if(button_p->elem.images[button_p->status])
        {
            button_p->elem.images[button_p->status]->base.paint_hdlr((as_control*)button_p->elem.images[button_p->status]);
        }
    }

    as_reset_layer_clip(layer);
}

static ASVOID as_ctrl_button_paint(as_control* ctrl_p)
{
    as_button* button_p = (as_button*)ctrl_p;

    if(!button_p || ctrl_p->if_hidden)
        return;

    switch(button_p->type)
    {
        case AS_TEXT_BUTTON:
            as_ctrl_text_button_paint(ctrl_p);
            break;

        case AS_IMAGE_BUTTON:
            as_ctrl_image_button_paint(ctrl_p);
            break;

        default:
            //warn
            break;
    }
}

static as_ret as_ctrl_button_change_status(as_control* ctrl_p, as_button_status status)
{
    as_ret ret = AS_OK;
    as_button* button_p = (as_button*)ctrl_p;

    if(!button_p || status == button_p->status)
    {
        return AS_INVALID_PARAM;
    }

    button_p->status = status;
    ctrl_p->paint_hdlr(ctrl_p);
    as_ctrl_flush();

    if(button_p->status == AS_BUTTON_DOWN || button_p->status == AS_BUTTON_UP)
    {
        if(button_p->cb[status])
            button_p->cb[status]();
    }

    return ret;
}

static as_ret as_ctrl_button_set_show_offset(as_control* ctrl_p, ASINT x_off, ASINT y_off)
{
    as_button* button_p = (as_button*)ctrl_p;
    ASINT i;

    if(!button_p)
        return AS_INVALID_PARAM;

    if(button_p->type == AS_IMAGE_BUTTON)
    {
        for(i = 0; i < AS_BUTTON_STATUS_MAX; i++)
        {
            if(button_p->elem.images[i])
            {
                button_p->elem.images[i]->set_show_type((as_control*)button_p->elem.images[i], AS_IMAGE_CUSTOM);
                button_p->elem.images[i]->set_show_offset((as_control*)button_p->elem.images[i], x_off, y_off);
            }
        }
    }

    return AS_OK;
}

static as_ret as_ctrl_button_set_bg_color(as_control* ctrl_p, ASUINT color)
{
    as_button* button_p = (as_button*)ctrl_p;

    if(!button_p || button_p->bg_color == color)
        return AS_INVALID_PARAM;

    button_p->bg_color = color;

    if(button_p->elem.label)
    {
        button_p->elem.label->set_bg_color((as_control*)button_p->elem.label, button_p->bg_color);
        button_p->elem.label->set_bg_frame_color((as_control*)button_p->elem.label, button_p->bg_color);
    }

    return AS_OK;
}

static as_ret as_ctrl_button_reset_status(as_control* ctrl_p)
{
    as_ret ret = AS_OK;
    as_button* button_p = (as_button*)ctrl_p;

    if(!ctrl_p)
    {
        return AS_INVALID_PARAM;
    }

    button_p->status = AS_BUTTON_UP;
    ctrl_p->paint_hdlr(ctrl_p);
    as_ctrl_flush();
    return ret;
}

#define AS_CTRL_BUTTON_DELETE_ITEM_FROM_LIST(ctrl_p,list,list_counts,item) \
    {\
        as_ret ret = AS_OK;\
        as_button* button_p = (as_button*)ctrl_p;\
        ASINT i = 0;\
        \
        if(!button_p)\
        {\
            return AS_INVALID_PARAM;\
        }\
        \
        for (i = 0; i < list_counts; i++)\
        {\
            if(list[i] == item)\
            {\
                list[i] = 0x7fffffff;\
            }\
        }\
        return ret;\
    }


static as_ret as_ctrl_button_add_keycode(as_control* ctrl_p, ASINT key_code)
{
    as_ret ret = AS_OK;
    as_button* button_p = (as_button*)ctrl_p;
    ASINT i = 0;

    if(!button_p)
    {
        return AS_INVALID_PARAM;
    }

    for (i = 0; i < AS_BUTTON_SUPPORT_KEYCODE_MAX; i++)
    {
        if(button_p->key_code_list[i] == key_code)
        {
            return ret;
        }
    }

    for(i = 0; i < AS_BUTTON_SUPPORT_KEYCODE_MAX; i++)
    {
        if(button_p->key_code_list[i] == 0x7fffffff)
        {
            button_p->key_code_list[i] = key_code;
            break;
        }
    }

    return ret;
}

static as_ret as_ctrl_button_delete_keycode(as_control* ctrl_p, ASINT key_code)
{
    as_ret ret = AS_OK;
    as_button* button_p = (as_button*)ctrl_p;
    ASINT i = 0;

    if(!button_p)
    {
        return AS_INVALID_PARAM;
    }

    for (i = 0; i < AS_BUTTON_SUPPORT_KEYCODE_MAX; i++)
    {
        if(button_p->key_code_list[i] == key_code)
        {
            button_p->key_code_list[i] = 0x7fffffff;
        }
    }

    return ret;
}

static as_ret as_ctrl_button_set_cb_by_status(as_control* ctrl_p, as_button_status status, as_button_cb p)
{
    as_button* btn_p = (as_button*)ctrl_p;

    if(!btn_p)
        return AS_INVALID_PARAM;

    if(status == AS_BUTTON_UP || status == AS_BUTTON_DOWN)
    {
        btn_p->cb[status] = p;
        return AS_OK;
    }
    else
    {
        return AS_INVALID_PARAM;
    }
}

static as_ret as_ctrl_button_reset_cb_by_status(as_control* ctrl_p, as_button_status status)
{
    as_button* btn_p = (as_button*)ctrl_p;

    if(!btn_p)
        return AS_INVALID_PARAM;

    if(status == AS_BUTTON_UP || status == AS_BUTTON_DOWN)
    {
        btn_p->cb[status] = NULL;
        return AS_OK;
    }
    else
    {
        return AS_INVALID_PARAM;
    }
}

static as_ret as_ctrl_button_set_image_btn_trans(as_control* ctrl_p, ASINT if_trans)
{
    ASINT i;
    as_button* button_p = (as_button*)ctrl_p;

    if(!button_p || button_p->type != AS_IMAGE_BUTTON)
        return AS_INVALID_PARAM;

    for(i = 0; i < AS_BUTTON_STATUS_MAX; i++)
    {
        if(button_p->elem.images[i])
            button_p->elem.images[i]->set_if_trans((as_control*)button_p->elem.images[i], if_trans);
    }

    return AS_OK;
}

static as_ret as_ctrl_button_pen_hdlr(as_control* ctrl_p, ASINT event, ASINT x, ASINT y)
{
    as_ret ret = AS_OK;
    as_button* button_p = (as_button*)ctrl_p;

    if(!button_p)
    {
        return AS_INVALID_PARAM;
    }

    if(button_p->status == AS_BUTTON_DISABLE || ctrl_p->if_hidden)
    {
        return AS_IGNORE;
    }

    if(event != AS_EVT_TOUCH_DOWN && !button_p->if_selected_by_down_event)
    {
        return AS_IGNORE;
    }

    if(event == AS_EVT_TOUCH_DOWN && AS_POINT_IN_RECT(x, y, ctrl_p->area))
    {
        button_p->if_selected_by_down_event = TRUE;
        button_p->change_status(ctrl_p, AS_BUTTON_DOWN);
    }

    if(button_p->if_selected_by_down_event && event == AS_EVT_TOUCH_UP && AS_POINT_IN_RECT(x, y, ctrl_p->area))
    {
        button_p->if_selected_by_down_event = FALSE;
        button_p->change_status(ctrl_p, AS_BUTTON_UP);
    }
    else if(event == AS_EVT_TOUCH_MOVE && !AS_POINT_IN_RECT(x, y, ctrl_p->area))
    {
        button_p->if_selected_by_down_event = FALSE;
        button_p->reset_status(ctrl_p);
    }
    //else if(event != AS_EVT_TOUCH_DOWN && button_p->if_selected_by_down_event)
    //{
    //    button_p->if_selected_by_down_event = FALSE;
    //    button_p->reset_status(ctrl_p);
    //}
    else
    {
        return AS_IGNORE;
    }

    return ret;
}

static as_ret as_ctrl_button_key_hdlr(as_control* ctrl_p, ASINT event, ASINT keycode)
{
    as_button* button_p = (as_button*)ctrl_p;
    ASINT i = 0;

    if(!button_p)
    {
        return AS_INVALID_PARAM;
    }

    if(ctrl_p->if_hidden)
        return AS_IGNORE;

    for(i = 0; i < AS_BUTTON_SUPPORT_KEYCODE_MAX; i++)
    {
        if(button_p->key_code_list[i] == keycode)
        {
            if(event == AS_EVT_KEY_DOWN)
            {
                button_p->change_status(ctrl_p, AS_BUTTON_DOWN);
            }
            else if(event == AS_EVT_KEY_UP)
            {
                button_p->change_status(ctrl_p, AS_BUTTON_UP);
            }

            return AS_OK;
        }
    }

    return AS_IGNORE;
}

static ASVOID as_ctrl_button_move(as_control* ctrl_p, ASINT x_off, ASINT y_off)
{
    as_button* button_p = (as_button*)ctrl_p;

    if(!button_p)
        return;

    button_p->base.area.x += (ASINT16)x_off;
    button_p->base.area.y += (ASINT16)y_off;

    if(button_p->type == AS_TEXT_BUTTON)
    {
        if(button_p->elem.label)
            button_p->elem.label->base.move((as_control*)button_p->elem.label, x_off, y_off);
    }
    else if(button_p->type == AS_IMAGE_BUTTON)
    {
        ASINT i = 0;

        for (i = 0; i < ARRAY_SIZE(button_p->elem.images); i++)
        {
            if(button_p->elem.images[i])
                button_p->elem.images[i]->base.move((as_control*)button_p->elem.images[i], x_off, y_off);
        }
    }
}

as_button* as_ctrl_button_create(as_rect area, as_button_type type,
                                 ASWSTR param1, ASWSTR param2, ASWSTR param3, ASUINT img_src_type)
{
    as_button* button_p = NULL;
    ASINT i;

    if(type < AS_TEXT_BUTTON || type >= AS_BUTTON_TYPE_MAX || !param1 || as_wstrlen(param1) <= 0)
    {
        return button_p;
    }

    if(type == AS_IMAGE_BUTTON && (!param2 || as_wstrlen(param2) <= 0))
    {
        return button_p;
    }

    button_p = as_calloc(sizeof(as_button));

    if(button_p == NULL)
    {
        return button_p;
    }

    as_ctrl_init((as_control*)button_p, area);

    for(i = 0; i < AS_BUTTON_SUPPORT_KEYCODE_MAX; i++)
        button_p->key_code_list[i] = 0x7fffffff;

    button_p->base.paint_hdlr = as_ctrl_button_paint;
    button_p->base.ctrl_type = AS_CTRL_BUTTON;
    button_p->base.move = as_ctrl_button_move;
    button_p->base.pen_hdlr = as_ctrl_button_pen_hdlr;
    button_p->base.key_hdlr = as_ctrl_button_key_hdlr;
    button_p->if_selected_by_down_event = FALSE;
    button_p->type = type;
    button_p->status = AS_BUTTON_UP;
    button_p->change_status = as_ctrl_button_change_status;
    button_p->reset_status = as_ctrl_button_reset_status;
    button_p->add_keycode = as_ctrl_button_add_keycode;
    button_p->delete_keycode = as_ctrl_button_delete_keycode;
    button_p->set_cb_by_status = as_ctrl_button_set_cb_by_status;
    button_p->reset_cb_by_status = as_ctrl_button_reset_cb_by_status;
    button_p->set_show_offset = as_ctrl_button_set_show_offset;
    button_p->set_bg_color = as_ctrl_button_set_bg_color;
    button_p->set_image_btn_trans = as_ctrl_button_set_image_btn_trans;

    if(button_p->type == AS_TEXT_BUTTON)
    {
        ASUINT param[1];
        param[0] = (ASUINT)param1;
        button_p->elem.label = (as_label*)as_ctrl_create(AS_CTRL_LABEL, area, 1, (ASVOID**)param);

        if(!button_p->elem.label)
        {
            as_free(button_p);
            button_p = NULL;
            return button_p;
        }
    }
    else if(button_p->type == AS_IMAGE_BUTTON)
    {
        ASUINT param[3];
        //create status UP image
        param[0] = (ASUINT)img_src_type;
        param[1] = (ASUINT)param1;
        param[2] = (ASUINT)FALSE;
        button_p->elem.images[AS_BUTTON_UP] = (as_image*)as_ctrl_create(AS_CTRL_IMAGE, area, 3, (ASVOID**)param);

        if(!button_p->elem.images[AS_BUTTON_UP])
        {
            as_free(button_p);
            button_p = NULL;
            return button_p;
        }

        //create status DOWN image
        param[1] = (ASUINT)param2;
        button_p->elem.images[AS_BUTTON_DOWN] = (as_image*)as_ctrl_create(AS_CTRL_IMAGE, area, 3, (ASVOID**)param);

        if(!button_p->elem.images[AS_BUTTON_DOWN])
        {
            as_ctrl_destroy((as_control*)button_p->elem.images[AS_BUTTON_DOWN]);
            as_free(button_p);
            button_p = NULL;
            return button_p;
        }

        //create status DISABLE image
        if(param3 && as_wstrlen(param3) > 0)
        {
            param[1] = (ASUINT)param3;
            button_p->elem.images[AS_BUTTON_DISABLE] = (as_image*)as_ctrl_create(AS_CTRL_IMAGE, area, 3, (ASVOID**)param);

            if(!button_p->elem.images[AS_BUTTON_DISABLE])
            {
                as_ctrl_destroy((as_control*)button_p->elem.images[AS_BUTTON_DOWN]);
                as_ctrl_destroy((as_control*)button_p->elem.images[AS_BUTTON_DISABLE]);
                as_free(button_p);
                button_p = NULL;
                return button_p;
            }
        }
    }

    return button_p;
}

as_ret as_ctrl_button_destroy(as_button* ctrl_button_p)
{
    ASINT i = 0;

    if(!ctrl_button_p)
    {
        return AS_INVALID_PARAM;
    }

    if(ctrl_button_p->type == AS_TEXT_BUTTON)
    {
        if(ctrl_button_p->elem.label)
        {
            as_ctrl_destroy((as_control*)ctrl_button_p->elem.label);
            ctrl_button_p->elem.label = NULL;
        }
    }
    else if(ctrl_button_p->type == AS_IMAGE_BUTTON)
    {
        for(i = 0; i < AS_BUTTON_STATUS_MAX; i++)
        {
            if(ctrl_button_p->elem.images[i])
            {
                as_ctrl_destroy((as_control*)ctrl_button_p->elem.images[i]);
                ctrl_button_p->elem.images[i] = NULL;
            }
        }
    }
    else
    {
        //warning
    }

    as_free(ctrl_button_p);
    return AS_OK;
}